from fastapi import APIRouter, Depends
from sqlalchemy.ext.asyncio import AsyncSession
from extends.db import get_db
from typing import Union
from service.user import Service
from repository.user import Repository
from domain.user import (WriteUser, ReadUser,
                         WriteRole, ReadRole,
                         WritePower, ReadPower,
                         ReadRoleToPower, ReadUserToRole,ReadUserToRoleToPowers, HasPermission, UpdateUser
                         )
from domain import ResponseModel
from repository import RepositoryNotFoundExt
##############
## 控制层(入口)
##############


# 注册依赖
async def create_service(db: AsyncSession = Depends(get_db)):
    return Service(repository=Repository(session=db))

########
# 用户
########
user_router = APIRouter()

@user_router.post("/")
async def create_user(write_data: WriteUser, service: Service = Depends(create_service)) -> ReadUser:
    user = await service.create_user(write_data.model_dump())
    return user

@user_router.get("/{user_id}")
async def get_user(user_id: int, service: Service = Depends(create_service)) -> ReadUser:
    user = await service.get_user(user_id)
    return user


@user_router.put("/{user_id}", response_model=ResponseModel)
async def update_user(user_id: int, update_data: UpdateUser, service: Service = Depends(create_service)):
    count = await service.update_user(user_id, update_data.model_dump())
    return ResponseModel(code=1, msg="ok", data={"count": count})


@user_router.post("/has_perm")
async def has_perm(data: HasPermission, service: Service = Depends(create_service)) -> bool:
    return await service.has_perm(data.user_id, data.power_name)

@user_router.get("/power/{user_id}")
async def get_user_role_powers(user_id: int, service: Service = Depends(create_service)) -> ReadUserToRoleToPowers:
    user = await service.get_user_role_powers(user_id)
    return user


@user_router.get("/")
async def get_users(page_size: int = 10, page_number: int = 1, service: Service = Depends(create_service)) -> list[ReadUser]:
    users = await service.get_users(page_size, page_number)
    return users


# @user_router.put("/{user_id}", response_model=ReadUser)
# async def update_user(user_id: int, update_data: WriteUser, service: Service = Depends(create_service)):
#     await service.update_user(user_id, update_data.model_dump())
#     return {"msg": "ok"}

@user_router.post("/{user_id}/role/{role_id}")
async def user_append_role(user_id: int, role_id: int, service: Service = Depends(create_service)) -> Union[ReadUserToRole, dict]:
    try:
        user = await service.user_append_role(user_id, role_id)
    except RepositoryNotFoundExt as e:
        return {"msg": e.args[0]}
    return user

@user_router.get("/{user_id}/role", response_model=ReadUserToRole)
async def get_user_roles(user_id: int, service: Service = Depends(create_service)):
    user = await service.get_user_roles(user_id)
    return user

#######
# 角色
#######
role_router = APIRouter()

@role_router.post("/")
async def create_role(write_data: WriteRole, service: Service = Depends(create_service)):
    role = await service.create_role(write_data.model_dump())
    return role

@role_router.get("/{role_id}", response_model=ReadRole)
async def get_role(role_id: int, service: Service = Depends(create_service)):
    role = await service.get_role(role_id)
    return role

@role_router.post("/{role_id}/power/{power_id}", response_model=ReadRoleToPower)
async def role_append_power(role_id: int, power_id: int, service: Service = Depends(create_service)) -> Union[ReadRoleToPower, dict]:
    role = await service.role_append_power(role_id, power_id)
    return role


@role_router.get("/{role_id}/power", response_model=ReadRoleToPower)
async def get_role_powers(role_id: int, service: Service = Depends(create_service)):
    role = await service.get_role_powers(role_id)
    return role

######
# 权限
######
power_router = APIRouter()


@power_router.get("/")
async def get_powers(page_size: int = 10, page_number: int = 1, service: Service = Depends(create_service)) -> list[ReadPower]:
    powers = await service.get_powers(page_size, page_number)
    return powers


@power_router.post("/")
async def create_power(write_data: WritePower, service: Service = Depends(create_service)):
    power = await service.create_power(write_data.model_dump())
    return power

@power_router.get("/{power_id}", response_model=ReadPower)
async def get_power(power_id: int, service: Service = Depends(create_service)):
    power = await service.get_power(power_id)
    return power